home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Comunicatii / htttrack / httrack-3.32-2.exe / {app} / src / htsname.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-04-24  |  47.3 KB  |  1,404 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       savename routine (compute output filename)             */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. /* Internal engine bytecode */
  39. #define HTS_INTERNAL_BYTECODE
  40.  
  41. #include "htsname.h"
  42.  
  43. /* specific definitions */
  44. #include "htsbase.h"
  45. #include "htstools.h"
  46. #include "htsmd5.h"
  47. #include <ctype.h>
  48. /* END specific definitions */
  49.  
  50. #undef test_flush
  51. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  52.  
  53. #define ADD_STANDARD_PATH \
  54.     {  /* ajout nom */\
  55.       char buff[HTS_URLMAXSIZE*2];\
  56.       buff[0]='\0';\
  57.       strncatbuff(buff,start_pos,(int) (nom_pos - start_pos));\
  58.       url_savename_addstr(save,buff);\
  59.     }
  60.  
  61. #define ADD_STANDARD_NAME(shortname) \
  62.     {  /* ajout nom */\
  63.       char buff[HTS_URLMAXSIZE*2];\
  64.       standard_name(buff,dot_pos,nom_pos,fil_complete,(shortname));\
  65.       url_savename_addstr(save,buff);\
  66.     }
  67.  
  68.  
  69. /* Avoid stupid DOS system folders/file such as 'nul' */
  70. /* Based on linux/fs/umsdos/mangle.c */
  71. static const char *hts_tbdev[] =
  72. {
  73.     "/prn", "/con", "/aux", "/nul",
  74.     "/lpt1", "/lpt2", "/lpt3", "/lpt4",
  75.     "/com1", "/com2", "/com3", "/com4",
  76.     "/clock$",
  77.     "/emmxxxx0", "/xmsxxxx0", "/setverxx",
  78.     ""
  79. };
  80.  
  81.  
  82.  
  83. // forme le nom du fichier α sauver (save) α partir de fil et adr
  84. // systΦme intelligent, qui renomme en cas de besoin (exemple: deux INDEX.HTML et index.html)
  85. int url_savename(char* adr_complete,char* fil_complete,char* save,char* former_adr,char* former_fil,char* referer_adr,char* referer_fil,httrackp* opt,lien_url** liens,int lien_tot,lien_back* back,int back_max,cache_back* cache,hash_struct* hash,int ptr,int numero_passe) {
  86.   char newfil[HTS_URLMAXSIZE*2];   /* ="" */
  87.   /*char normadr_[HTS_URLMAXSIZE*2];*/
  88.   char normfil_[HTS_URLMAXSIZE*2];
  89.   int protocol = 0;
  90.   static const char* protocol_str[] = {"http", "https", "ftp", "file", "unknown"};
  91.   char* normadr;
  92.   char* normfil;
  93.   char* fil;
  94.   char* adr;
  95.   char* print_adr;
  96.   char *start_pos=NULL,*nom_pos=NULL,*dot_pos=NULL;  // Position nom et point
  97.   // pour changement d'extension ou de nom (content-disposition)
  98.   int ext_chg=0;
  99.   char ext[256];
  100.   int max_char=0;
  101.   //CLEAR
  102.   newfil[0]=ext[0]='\0';
  103.  
  104.   /* 8-3 ? */
  105.   switch(opt->savename_83) {
  106.   case 1:
  107.     max_char=8;
  108.     break;
  109.   case 2:
  110.     max_char=30;
  111.     break;
  112.   default:
  113.     max_char=8;
  114.     break;
  115.   }
  116.  
  117.   // effacer save
  118.   save[0]='\0';
  119.   // fil
  120.   fil = fil_complete;
  121.   // copy of fil, used for lookups (see urlhack)
  122.   normfil = fil;
  123.   // et adr (sauter user/pass)
  124.   // on prend le parti de mettre les fichiers avec login/pass au mΩme endroit que si ils
  125.   // Θtaient capturΘs sans ces paramΦtres
  126.   // c'est pour cette raison qu'on ignore totalement adr_complete (mΩme pour la recherche en table de hachage)
  127.   adr = jump_identification(adr_complete);
  128.   // copy of adr, used for lookups (see urlhack)
  129.   normadr = adr;
  130.  
  131.   // normalize the URL:
  132.   // www.foo.com -> foo.com
  133.   // www-42.foo.com -> foo.com
  134.   // foo.com/bar//foobar -> foo.com/bar/foobar
  135.   if (opt->urlhack) {
  136.     // copy of adr (withiotu protocol), used for lookups (see urlhack)
  137.     normadr=jump_normalized(adr);
  138.     normfil=fil_normalized(fil,normfil_);
  139.   }
  140.  
  141.   // α afficher sans ftp://
  142.   print_adr=jump_protocol(adr);
  143.   if (strfield(adr_complete, "https:")) {
  144.       protocol = 1;
  145.   } else if (strfield(adr_complete, "ftp:")) {
  146.       protocol = 2;
  147.   } else if (strfield(adr_complete, "file:")) {
  148.       protocol = 3;
  149.   } else {
  150.       protocol = 0;
  151.   }
  152.  
  153.   // court-circuit pour lien primaire
  154.   if (strnotempty(adr)==0) {
  155.     if (strcmp(fil,"primary")==0) {
  156.       strcatbuff(save,"primary.html");
  157.       return 0;
  158.     }
  159.   }
  160.  
  161.  
  162.   // vΘrifier que le nom n'a pas dΘja ΘtΘ calculΘ (si oui le renvoyer tel que)
  163.   // vΘrifier que le nom n'est pas dΘja pris...
  164.   // NOTE: si on cherche /toto/ et que /toto est trouvΘ on le prend (et rΘciproquqment) ** // **
  165.   if (liens!=NULL) { 
  166.     int i;
  167.  
  168. #if HTS_HASH
  169.     i=hash_read(hash,normadr,normfil,1,opt->urlhack);      // recherche table 1 (adr+fil)
  170.     if (i>=0) {    // ok, trouvΘ
  171.       strcpybuff(save,liens[i]->sav);
  172.       return 0;
  173.     }
  174.     i=hash_read(hash,normadr,normfil,2,opt->urlhack);      // recherche table 2 (former_adr+former_fil)
  175.     if (i>=0) {    // ok, trouvΘ
  176.       // copier location moved!
  177.       strcpybuff(adr_complete,liens[i]->adr);
  178.       strcpybuff(fil_complete,liens[i]->fil);
  179.       // et save
  180.       strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  181.       return 0;
  182.     }
  183. #else
  184.     for(i=lien_tot-1;i>=0;i--) {        
  185. #if HTS_CASSE
  186.       if ((strcmp(liens[i]->adr,normadr)==0) && (strcmp(liens[i]->fil,normfil)==0))
  187. #else
  188.       if ((strfield2(liens[i]->adr,normadr)) && (strfield2(liens[i]->fil,normfil)))
  189. #endif
  190.       {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  191.         strcpybuff(save,liens[i]->sav);
  192.         return 0;
  193.       }
  194.       if (liens[i]->former_adr) {     // tester ancienne loc?
  195. #if HTS_CASSE
  196.         if ((strcmp(liens[i]->former_adr,normadr)==0) && (strcmp(liens[i]->former_fil,normfil)==0))
  197. #else
  198.         if ((strfield2(liens[i]->former_adr,normadr)) && (strfield2(liens[i]->former_fil,normfil)))
  199. #endif
  200.         {
  201.           // copier location moved!
  202.           strcpybuff(adr_complete,liens[i]->adr);
  203.           strcpybuff(fil_complete,liens[i]->fil);
  204.           // et save
  205.           strcpybuff(save,liens[i]->sav);  // copier (formΘ α partir du nouveau lien!)
  206.           return 0;
  207.         }
  208.       }
  209.     }
  210. #endif
  211.  
  212.     // chercher sans / ou avec / dans former
  213.     {
  214.       char fil_complete_patche[HTS_URLMAXSIZE*2];
  215.       strcpybuff(fil_complete_patche,normfil);
  216.       // Version avec ou sans /
  217.       if (fil_complete_patche[strlen(fil_complete_patche)-1]=='/')
  218.         fil_complete_patche[strlen(fil_complete_patche)-1]='\0';
  219.       else
  220.         strcatbuff(fil_complete_patche,"/");
  221. #if HTS_HASH
  222.       i=hash_read(hash,normadr,fil_complete_patche,2,opt->urlhack);      // recherche table 2 (former_adr+former_fil)
  223.       if (i>=0) {
  224.         // Θcraser fil et adr (pas former_fil?????)
  225.         strcpybuff(adr_complete,liens[i]->adr);
  226.         strcpybuff(fil_complete,liens[i]->fil);
  227.         // Θcrire save
  228.         strcpybuff(save,liens[i]->sav);
  229.         return 0;
  230.       }
  231. #else
  232.       // mΩme boucle en gros
  233.       for(i=lien_tot-1;i>=0;i--) {        
  234.         if (liens[i]->former_adr) {    // former-adr?
  235. #if HTS_CASSE
  236.           if ((strcmp(liens[i]->former_adr,normadr)==0) && (strcmp(liens[i]->former_fil,fil_complete_patche)==0))
  237. #else
  238.           if ((strfield2(liens[i]->former_adr,normadr)) && (strfield2(liens[i]->former_fil,fil_complete_patche)))
  239. #endif
  240.           {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  241.             // Θcraser fil et adr (pas former_fil?????)
  242.             strcpybuff(adr_complete,liens[i]->adr);
  243.             strcpybuff(fil_complete,liens[i]->fil);
  244.             // Θcrire save
  245.             strcpybuff(save,liens[i]->sav);
  246.             return 0;
  247.           }
  248.         }
  249.       }
  250. #endif
  251.     }
  252.   }
  253.  
  254.   // vΘrifier la non prΘsence de paramΦtres dans le nom de fichier
  255.   // si il y en a, les supprimer (ex: truc.cgi?subj=aspirateur)
  256.   // nΘanmoins, gardΘ pour vΘrifier la non duplication (voir aprΦs)
  257.   {
  258.     char* a;
  259.     a=strchr(fil,'?');
  260.     if (a!=NULL) {
  261.       strncatbuff(newfil,fil,(int) (a - fil));
  262.     } else {
  263.       strcpybuff(newfil,fil);
  264.     }
  265.     fil=newfil;
  266.   }
  267.   // dΘcoder %
  268.   strcpybuff(fil,unescape_http(fil));
  269.   /*
  270.   {
  271.     char tempo[HTS_URLMAXSIZE*2];
  272.     int i,j=0;
  273.     for (i=0;i<(int) strlen(fil);i++) {
  274.       if (fil[i]=='%') {
  275.         i++;
  276.         tempo[j++]=(char) ehex(fil+i);
  277.         i++;    // sauter 2 caractΦres finalement
  278.       } else
  279.         tempo[j++]=fil[i];
  280.     }
  281.     tempo[j++]='\0';
  282.     strcpybuff(fil,tempo);
  283.   }
  284.   */
  285.   
  286.   
  287.   /* replace shtml to html.. */
  288.   switch (ishtml(fil)) {       /* .html,.shtml,.. */
  289.   case 1:
  290.     if ( 
  291.       (strfield2(get_ext(fil),"html") == 0)
  292.       && (strfield2(get_ext(fil),"htm") == 0)
  293.       ) {
  294.       strcpybuff(ext,"html");
  295.       ext_chg=1;
  296.     }
  297.     break;
  298.     case 0:
  299.       if (!strnotempty(ext)) {
  300.         if (is_userknowntype(get_ext(fil))) {      // mime known by user
  301.           char mime[1024];
  302.           mime[0]=ext[0]='\0';
  303.           get_userhttptype(0,mime,get_ext(fil));
  304.           if (strnotempty(mime)) {
  305.             give_mimext(ext,mime);
  306.             if (strnotempty(ext)) {
  307.               ext_chg=1;
  308.             }
  309.           }
  310.         }
  311.       }
  312.       break;
  313.   }
  314.   
  315.  
  316.   // si option check_type activΘe
  317.   if ((opt->check_type) && (!ext_chg)) {
  318.     int ishtest;
  319.     if ( (!strfield(adr_complete,"file://")) 
  320.       && (!strfield(adr_complete,"ftp://")) 
  321.       ) {
  322.       // tester type avec requΦte HEAD si on ne connait pas le type du fichier
  323.       if (!(   (opt->check_type==1) && (fil[strlen(fil)-1]=='/')   ))    // slash doit Ωtre html?
  324.       if ((ishtest=ishtml(fil)) < 0) { // on ne sait pas si c'est un html ou un fichier..
  325.         // lire dans le cache
  326.         htsblk r = cache_read(opt,cache,adr,fil,NULL,NULL);              // test uniquement
  327.         if (r.statuscode != -1) {  // pas d'erreur de lecture cache
  328.           char s[16]; s[0]='\0';
  329.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  330.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type (from cache) %s%s"LF,adr_complete,fil_complete);
  331.             test_flush;
  332.           }
  333.           if (strnotempty(r.cdispo)) {        /* filename given */
  334.             ext_chg=2;      /* change filename */
  335.             strcpybuff(ext,r.cdispo);
  336.           }
  337.           else if (!may_unknown(r.contenttype) || ishtest == -2) {  // on peut patcher α priori?
  338.             give_mimext(s,r.contenttype);  // obtenir extension
  339.             if (strnotempty(s)>0) {        // on a reconnu l'extension
  340.               ext_chg=1;
  341.               strcpybuff(ext,s);
  342.             }
  343.           }
  344.           //
  345.         } else {          // test imposible dans le cache, faire une requΩte
  346.           //
  347. #if HTS_ANALYSTE
  348.           int hihp=_hts_in_html_parsing;
  349. #endif
  350.           int has_been_moved=0;
  351.           char curr_adr[HTS_URLMAXSIZE*2],curr_fil[HTS_URLMAXSIZE*2];
  352.           
  353.           /* Ensure we don't use too many sockets by using a "testing" one
  354.              If we have only 1 simultaneous connection authorized, wait for pending download
  355.              Wait for an available slot 
  356.           */
  357.           int ActiveSockets = back_nsoc(back,back_max);
  358.           int TotalSockets = back_nsoc_overall(back,back_max);
  359.           if (opt->maxconn > 0) {
  360.             while (back_nsoc(back,back_max) >= opt->maxsoc) {
  361.               // Wait ..
  362.               back_wait(back,back_max,opt,cache,0);        
  363.  
  364.               // Transfer rate
  365.               engine_stats();
  366.               
  367.               // Refresh various stats
  368.               HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  369.               HTS_STAT.stat_errors=fspc(NULL,"error");
  370.               HTS_STAT.stat_warnings=fspc(NULL,"warning");
  371.               HTS_STAT.stat_infos=fspc(NULL,"info");
  372.               HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  373.               HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  374.               
  375.               // Check
  376.               if (!hts_htmlcheck_loop(back,back_max,-1,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  377.                 return -1;
  378.               }
  379.             }
  380.           }
  381.           ActiveSockets = back_nsoc(back,back_max);
  382.           TotalSockets = back_nsoc_overall(back,back_max);
  383.  
  384.           /* Rock'in */
  385.           curr_adr[0]=curr_fil[0]='\0';
  386. #if HTS_ANALYSTE
  387.           _hts_in_html_parsing=2;  // test
  388. #endif
  389.           if ( (opt->debug>1) && (opt->log!=NULL) ) {
  390.             fspc(opt->log,"debug"); fprintf(opt->log,"Testing link type %s%s"LF,adr_complete,fil_complete);
  391.             test_flush;
  392.           }
  393.           strcpybuff(curr_adr,adr_complete);
  394.           strcpybuff(curr_fil,fil_complete);
  395.           // ajouter dans le backing le fichier en mode test
  396.           // savename: rien car en mode test
  397.           if (back_add(back,back_max,opt,cache,curr_adr,curr_fil,BACK_ADD_TEST,referer_adr,referer_fil,1,NULL)!=-1) {
  398.             int b;
  399.             b=back_index(back,back_max,curr_adr,curr_fil,BACK_ADD_TEST);         
  400.             if (b>=0) {
  401.               int stop_looping=0;
  402.               int petits_tours=0;
  403.               int get_test_request=0;       // en cas de bouclage sur soi mΩme avec HEAD, tester avec GET.. parfois c'est la cause des problΦmes
  404.               do {
  405.                 // temps α attendre, et remplir autant que l'on peut le cache (backing)
  406.                 if (back[b].status>0) {
  407.                   back_wait(back,back_max,opt,cache,0);        
  408.                 }
  409.                 if (ptr>=0) {
  410.                   back_fillmax(back,back_max,opt,cache,liens,ptr,numero_passe,lien_tot);
  411.                 }
  412.   
  413.                 // on est obligΘ d'appeler le shell pour le refresh..
  414. #if HTS_ANALYSTE
  415.                 {
  416.                   
  417.                   // Transfer rate
  418.                   engine_stats();
  419.                   
  420.                   // Refresh various stats
  421.                   HTS_STAT.stat_nsocket=back_nsoc(back,back_max);
  422.                   HTS_STAT.stat_errors=fspc(NULL,"error");
  423.                   HTS_STAT.stat_warnings=fspc(NULL,"warning");
  424.                   HTS_STAT.stat_infos=fspc(NULL,"info");
  425.                   HTS_STAT.nbk=backlinks_done(liens,lien_tot,ptr);
  426.                   HTS_STAT.nb=back_transfered(HTS_STAT.stat_bytes,back,back_max);
  427.  
  428.                   if (!hts_htmlcheck_loop(back,back_max,b,ptr,lien_tot,(int) (time_local()-HTS_STAT.stat_timestart),&HTS_STAT)) {
  429.                     return -1;
  430.                   } else if (_hts_cancel || !back_checkmirror(opt)) {    // cancel 2 ou 1 (cancel parsing)
  431.                     back_delete(opt,cache,back,b);       // cancel test
  432.                     stop_looping = 1;
  433.                   }
  434.                 }
  435. #endif
  436.                 
  437.                 
  438.                 // traitement des 304,303..
  439.                 if (back[b].status<=0) {
  440.                   if (    (back[b].r.statuscode==301)
  441.                        || (back[b].r.statuscode==302)
  442.                        || (back[b].r.statuscode==303)
  443.                        || (back[b].r.statuscode==307)
  444.                      ) {    // agh moved.. un tit tour de plus
  445.                     if ((petits_tours<5) && (former_adr) && (former_fil)) { // on va pas tourner en rond non plus!
  446.                       if ((int) strnotempty(back[b].r.location)) {    // location existe!
  447.                         char mov_url[HTS_URLMAXSIZE*2],mov_adr[HTS_URLMAXSIZE*2],mov_fil[HTS_URLMAXSIZE*2];
  448.                         mov_url[0]=mov_adr[0]=mov_fil[0]='\0';
  449.                         //
  450.                         strcpybuff(mov_url,back[b].r.location);    // copier URL
  451.                         if (ident_url_relatif(mov_url,curr_adr,curr_fil,mov_adr,mov_fil)>=0) {                        
  452.                           // si non bouclage sur soi mΩme, ou si test avec GET non testΘ
  453.                           if ((strcmp(mov_adr,curr_adr)) || (strcmp(mov_fil,curr_fil)) || (get_test_request==0)) {
  454.                             // bouclage?
  455.                             if ((!strcmp(mov_adr,curr_adr)) && (!strcmp(mov_fil,curr_fil)))
  456.                               get_test_request=1;     // faire requΦte avec GET
  457.  
  458.                             // recopier former_adr/fil?
  459.                             if ((former_adr) && (former_fil)) {
  460.                               if (strnotempty(former_adr)==0) {    // Pas dΘja notΘ
  461.                                 strcpybuff(former_adr,curr_adr);
  462.                                 strcpybuff(former_fil,curr_fil);
  463.                               }
  464.                             }
  465.  
  466.                             // check explicit forbidden - don't follow 3xx in this case
  467.                             {
  468.                               int set_prio_to=0;
  469.                               robots_wizard* robots = (robots_wizard*) opt->robotsptr;
  470.                               if (hts_acceptlink(opt,ptr,lien_tot,liens,
  471.                                 mov_adr,mov_fil,
  472.                                 NULL, NULL,
  473.                                 &set_prio_to,
  474.                                 NULL) == 1) 
  475.                               {  /* forbidden */
  476.                                 has_been_moved = 1;
  477.                                 back_maydelete(opt,cache,back,b);    // ok
  478.                                 strcpybuff(curr_adr,mov_adr);
  479.                                 strcpybuff(curr_fil,mov_fil);
  480.                                 mov_url[0]='\0';
  481.                                 stop_looping = 1;
  482.                               }
  483.                             }
  484.                             
  485.                             // ftp: stop!
  486.                             if (strfield(mov_url,"ftp://")) {    // ftp, ok on arrΩte
  487.                               has_been_moved = 1;
  488.                               back_maydelete(opt,cache,back,b);    // ok
  489.                               strcpybuff(curr_adr,mov_adr);
  490.                               strcpybuff(curr_fil,mov_fil);
  491.                               stop_looping = 1;
  492.                             } else if (*mov_url) {
  493.                               char* methode;
  494.                               if (!get_test_request)
  495.                                 methode=BACK_ADD_TEST;      // tester avec HEAD
  496.                               else {
  497.                                 methode=BACK_ADD_TEST2;     // tester avec GET
  498.                                 if ( opt->errlog!=NULL ) {
  499.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Loop with HEAD request (during prefetch) at %s%s"LF,curr_adr,curr_fil);
  500.                                   test_flush;
  501.                                 }                    
  502.                               }
  503.                               // Ajouter
  504.                               if (back_add(back,back_max,opt,cache,mov_adr,mov_fil,methode,referer_adr,referer_fil,1,NULL)!=-1) {    // OK
  505.                                 if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  506.                                   fspc(opt->errlog,"warning"); fprintf(opt->errlog,"(during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  507.                                   test_flush;
  508.                                 }
  509.                                 
  510.                                 // libΘrer emplacement backing actuel et attendre le prochain
  511.                                 back_maydelete(opt,cache,back,b);
  512.                                 strcpybuff(curr_adr,mov_adr);
  513.                                 strcpybuff(curr_fil,mov_fil);
  514.                                 b=back_index(back,back_max,curr_adr,curr_fil,methode);         
  515.                                 if (!get_test_request)
  516.                                   has_been_moved = 1;       // sinon ne pas forcer has_been_moved car non dΘplacΘ
  517.                                 petits_tours++;
  518.                                 //
  519.                               } else {// sinon on fait rien et on s'en va.. (ftp etc)
  520.                                 if ( (opt->debug>1)  && (opt->errlog)) {
  521.                                   fspc(opt->errlog,"debug"); fprintf(opt->errlog,"Warning: Savename redirect backing error at %s%s"LF,mov_adr,mov_fil);
  522.                                   test_flush;
  523.                                 } 
  524.                               }
  525.                             }
  526.                           } else {
  527.                             if ( opt->errlog!=NULL ) {
  528.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop to same filename)"LF,adr_complete,fil_complete);
  529.                               test_flush;
  530.                             }
  531.                           }
  532.                           
  533.                         }
  534.                       }
  535.                     } else{  // arrΩter les frais
  536.                       if ( opt->errlog!=NULL ) {
  537.                         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Unable to test %s%s (loop)"LF,adr_complete,fil_complete);
  538.                         test_flush;
  539.                       }
  540.                     }
  541.                   }  // ok, leaving
  542.                 }
  543.               } while(!stop_looping && back[b].status > 0 && back[b].status < 1000);
  544.               
  545.               // Si non dΘplacΘ, forcer type?
  546.               if (!has_been_moved) {
  547.                 if (back[b].r.statuscode!=-10) {    // erreur
  548.                   if (strnotempty(back[b].r.contenttype)==0)
  549.                     strcpybuff(back[b].r.contenttype,"text/html");    // message d'erreur en html
  550.                   // Finalement on, renvoie un erreur, pour ne toucher α rien dans le code
  551.                   // libΘrer emplacement backing
  552.                   /*if (opt->errlog!=NULL) {
  553.                     fspc(opt->errlog,0); fprintf(opt->errlog,"Error: (during prefetch) %s (%d) to link %s at %s%s"LF,back[b].r.msg,back[b].r.statuscode,back[b].r.location,curr_adr,curr_fil);
  554.                     test_flush;
  555.                   }                    
  556.                   back_delete(opt,cache,back,b);
  557.                   return -1;        // ERREUR (404 par exemple)
  558.                   */
  559.                 } 
  560.                 
  561.                 {            // pas d'erreur, changer type?
  562.                   char s[16];
  563.                   s[0]='\0';
  564.                   if (strnotempty(back[b].r.cdispo)) {        /* filename given */
  565.                     ext_chg=2;      /* change filename */
  566.                     strcpybuff(ext,back[b].r.cdispo);
  567.                   }
  568.                   else if (!may_unknown(back[b].r.contenttype) || ishtest == -2 ) {  // on peut patcher α priori? (pas interdit ou pas de type)
  569.                     give_mimext(s,back[b].r.contenttype);  // obtenir extension
  570.                     if (strnotempty(s)>0) {    // on a reconnu l'extension
  571.                       ext_chg=1;
  572.                       strcpybuff(ext,s);
  573.                     }
  574.                   }
  575.                 }
  576.               }
  577.               // FIN Si non dΘplacΘ, forcer type?
  578.  
  579.               // libΘrer emplacement backing
  580.               back_maydelete(opt,cache,back,b);
  581.               
  582.               // --- --- ---
  583.               // oops, a ΘtΘ dΘplacΘ.. on recalcule en rΘcursif (osons!)
  584.               if (has_been_moved) {
  585.                 // copier adr, fil (optionnel, mais sinon marche pas pour le rip)
  586.                 strcpybuff(adr_complete,curr_adr);
  587.                 strcpybuff(fil_complete,curr_fil);
  588.                 // copier adr, fil
  589.                 
  590.                 return url_savename(curr_adr,curr_fil,save,NULL,NULL,referer_adr,referer_fil,opt,liens,lien_tot,back,back_max,cache,hash,ptr,numero_passe);
  591.               }
  592.               // --- --- ---
  593.               
  594.             }
  595.             
  596.           } else {
  597.             printf("PANIC! : Savename Crash adding error, unexpected error found.. [%d]\n",__LINE__);
  598. #if BDEBUG==1
  599.             printf("error while savename crash adding\n");
  600. #endif
  601.             if (opt->errlog) {
  602.               fspc(opt->errlog,"error"); fprintf(opt->errlog,"Unexpected savename backing error at %s%s"LF,adr,fil_complete);
  603.               test_flush;
  604.             } 
  605.             
  606.           }
  607.           // restaurer
  608. #if HTS_ANALYSTE
  609.           _hts_in_html_parsing=hihp;
  610. #endif
  611.         }  // cachΘ?
  612.       }
  613.     }
  614.   }
  615.  
  616.  
  617.  
  618.   // - - - DEBUT NOMMAGE - - -
  619.  
  620.   // Donner nom par dΘfaut?
  621.   if (fil[strlen(fil)-1]=='/')  {
  622.     if (!strfield(adr_complete,"ftp://"))
  623.       strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut!!
  624.     else {
  625.       if (!opt->proxy.active)
  626.         strcatbuff(fil,DEFAULT_FTP);     // nommer page par dΘfaut (texte)
  627.       else
  628.         strcatbuff(fil,DEFAULT_HTML);     // nommer page par dΘfaut (α priori ici html depuis un proxy http)
  629.     }
  630.   }
  631.   // Changer extension?
  632.   // par exemple, php3 sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  633.   if (ext_chg) {  // changer ext
  634.     char* a=fil+strlen(fil)-1;
  635.     if ( (opt->debug>1) && (opt->log!=NULL) ) {
  636.       fspc(opt->log,"debug");
  637.       if (ext_chg==1)
  638.         fprintf(opt->log,"Changing link extension %s%s to .%s"LF,adr_complete,fil_complete,ext);
  639.       else
  640.         fprintf(opt->log,"Changing link name %s%s to %s"LF,adr_complete,fil_complete,ext);
  641.       test_flush;
  642.     }
  643.     if (ext_chg==1) {
  644.       while((a > fil) && (*a!='.') && (*a!='/')) a--;
  645.       if (*a=='.') *a='\0';  // couper
  646.       strcatbuff(fil,".");      // recopier point
  647.     } else {
  648.       while(( a > fil) && (*a!='/')) a--;
  649.       if (*a=='/') a++;
  650.       *a='\0';
  651.    }
  652.     strcatbuff(fil,ext);    // copier ext/nom
  653.   }
  654.  
  655.   // Rechercher premier / et dernier .
  656.   {  
  657.     char* a=fil+strlen(fil)-1;
  658.  
  659.     // passer structures
  660.     start_pos=fil;
  661.     while(( a > fil) && (*a != '/') && (*a != '\\')) {
  662.       if (*a == '.')    // point? noter position
  663.         if (!dot_pos)
  664.           dot_pos=a;
  665.         a--;
  666.     }
  667.     if ((*a=='/') || (*a=='\\')) a++;
  668.     nom_pos = a;
  669.   }
  670.  
  671.   
  672.   // un nom de fichier est gΘnΘrΘ
  673.   // s'il existe dΘja, alors on le mofifie lΘgΦrement
  674.  
  675.   // ajouter nom du site Θventuellement en premier
  676.   if (opt->savename_type == -1) {    // utiliser savename_userdef! (%h%p/%n%q.%t)
  677.     char* a = opt->savename_userdef;
  678.     char* b = save;
  679.     /*char *nom_pos=NULL,*dot_pos=NULL;  // Position nom et point */
  680.     char tok;
  681.  
  682.     /*
  683.     {  // Rechercher premier /
  684.       char* a=fil+strlen(fil)-1;
  685.       // passer structures
  686.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) {
  687.         if (*a == '.')    // point? noter position
  688.         if (!dot_pos)
  689.           dot_pos=a;
  690.         a--;
  691.       }
  692.       if ((*a=='/') || (*a=='\\')) a++;
  693.       nom_pos = a;
  694.     }
  695.     */
  696.  
  697.     // Construire nom
  698.     while ((*a) && (((int) (b - save)) < HTS_URLMAXSIZE ) ) {    // parser, et pas trop long..
  699.       if (*a == '%') {
  700.         int short_ver=0;
  701.         a++;
  702.         if (*a == 's') {
  703.           short_ver=1;
  704.           a++;
  705.         }
  706.         *b='\0';
  707.         switch(tok=*a++) {
  708.           case '[':            // %[param:prefix_if_not_empty:suffix_if_not_empty:empty_replacement:notfound_replacement]
  709.             if (strchr(a,']')) {
  710.               int pos=0;
  711.               char name[5][256];
  712.               char* c=name[0];
  713.               for(pos = 0 ; pos < 5 ; pos++) {
  714.                 name[pos][0]='\0';
  715.               }
  716.               pos=0;
  717.               while(*a!=']') {
  718.                 if (pos < 5) {
  719.                   if (*a == ':') {  // next token
  720.                     c=name[++pos];
  721.                     a++;
  722.                   } else {
  723.                     *c++=*a++;
  724.                     *c='\0';
  725.                   }
  726.                 }
  727.               }
  728.               a++;
  729.               strcatbuff(name[0],"=");           /* param=.. */
  730.               c=strchr(fil_complete,'?');
  731.               /* parameters exists */
  732.               if (c) {
  733.                 char* cp;
  734.                 while((cp = strstr(c+1, name[0])) && *(cp-1) != '?' && *(cp-1) != '&') {     /* finds [?&]param= */
  735.                   c = cp;
  736.                 }
  737.                 if (cp) {
  738.                   c = cp + strlen(name[0]);    /* jumps "param=" */
  739.                   strcpybuff(b, name[1]);    /* prefix */
  740.                   b += strlen(b);
  741.                   if (*c != '\0' && *c != '&') {
  742.                     char* d = name[0];
  743.                     /* */
  744.                     while(*c != '\0' && *c != '&') {
  745.                       *d++ = *c++;
  746.                     }
  747.                     *d = '\0';
  748.                     d = unescape_http(name[0]);
  749.                     if (d && *d) {
  750.                       strcpybuff(b, d);         /* value */
  751.                       b += strlen(b);
  752.                     } else {
  753.                       strcpybuff(b, name[3]);    /* empty replacement if any */
  754.                       b += strlen(b);
  755.                     }
  756.                   } else {
  757.                     strcpybuff(b, name[3]);    /* empty replacement if any */
  758.                     b += strlen(b);
  759.                   }
  760.                   strcpybuff(b, name[2]);    /* suffix */
  761.                   b += strlen(b);
  762.                 } else {
  763.                   strcpybuff(b, name[4]);    /* not found replacement if any */
  764.                   b += strlen(b);
  765.                 }
  766.               }
  767.             }
  768.           break;
  769.           case '%': *b++='%'; break;
  770.           case 'n':    // nom sans ext
  771.             if (dot_pos) {
  772.               if (!short_ver)    // Noms longs
  773.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  774.               else
  775.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  776.             } else {
  777.               if (!short_ver)    // Noms longs
  778.                 strcpybuff(b,nom_pos);
  779.               else
  780.                 strncatbuff(b,nom_pos,8);
  781.             }
  782.             b+=strlen(b);   // pointer α la fin
  783.             break;
  784.           case 'N':    // nom avec ext
  785.             // RECOPIE NOM + EXT
  786.             *b='\0';
  787.             if (dot_pos) {
  788.               if (!short_ver)    // Noms longs
  789.                 strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  790.               else
  791.                 strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  792.             } else {
  793.               if (!short_ver)    // Noms longs
  794.                 strcpybuff(b,nom_pos);
  795.               else
  796.                 strncatbuff(b,nom_pos,8);
  797.             }
  798.             b+=strlen(b);   // pointer α la fin
  799.             // RECOPIE NOM + EXT
  800.             *b='\0';
  801.             if (dot_pos) {
  802.               if (!short_ver)    // Noms longs
  803.                 strcpybuff(b,dot_pos+1);
  804.               else
  805.                 strncatbuff(b,dot_pos+1,3);
  806.             } else {
  807.               if (!short_ver)    // Noms longs
  808.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  809.               else
  810.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  811.             }
  812.             b+=strlen(b);   // pointer α la fin
  813.             //
  814.             break;
  815.           case 't':    // ext
  816.             *b='\0';
  817.             if (dot_pos) {
  818.               if (!short_ver)    // Noms longs
  819.                 strcpybuff(b,dot_pos+1);
  820.               else
  821.                 strncatbuff(b,dot_pos+1,3);
  822.             } else {
  823.               if (!short_ver)    // Noms longs
  824.                 strcpybuff(b,DEFAULT_EXT);    // pas de..
  825.               else
  826.                 strcpybuff(b,DEFAULT_EXT_SHORT);    // pas de..
  827.             }
  828.             b+=strlen(b);   // pointer α la fin
  829.             break;
  830.           case 'p':    // path sans dernier /
  831.             *b='\0';
  832.             if (nom_pos != fil + 1) { // pas: /index.html (chemin nul)
  833.               if (!short_ver) {   // Noms longs
  834.                 strncatbuff(b,fil,(int) (nom_pos - fil) - 1);
  835.               } else {
  836.                 char pth[HTS_URLMAXSIZE*2],n83[HTS_URLMAXSIZE*2];
  837.                 pth[0]=n83[0]='\0';
  838.                 //
  839.                 strncatbuff(pth,fil,(int) (nom_pos - fil) - 1);
  840.                 long_to_83(opt->savename_83,n83,pth);
  841.                 strcpybuff(b,n83);
  842.               }
  843.             }
  844.             b+=strlen(b);   // pointer α la fin
  845.             break;
  846.           case 'h':    // host
  847.             *b='\0';
  848.             if (strcmp(adr_complete,"file://")==0) {
  849.               if (!short_ver)    // Noms longs
  850.                 strcpybuff(b,"localhost");
  851.               else
  852.                 strcpybuff(b,"local");
  853.             } else {
  854.               if (!short_ver)    // Noms longs
  855.                 strcpybuff(b,print_adr);
  856.               else
  857.                 strncatbuff(b,print_adr,8);
  858.             }
  859.             b+=strlen(b);   // pointer α la fin
  860.             break;
  861.           case 'M':         /* host/address?query MD5 (128-bits) */
  862.             *b='\0';
  863.             {
  864.               char digest[32+2];
  865.               char buff[HTS_URLMAXSIZE*2];
  866.               digest[0]=buff[0]='\0';
  867.               strcpybuff(buff,adr);
  868.               strcatbuff(buff,fil_complete);
  869.               domd5mem(buff,strlen(buff),digest,1);
  870.               strcpybuff(b,digest);
  871.             }
  872.             b+=strlen(b);   // pointer α la fin
  873.             break;
  874.           case 'Q': case 'q':         /* query MD5 (128-bits/16-bits) 
  875.                                          GENERATED ONLY IF query string exists! */
  876.             *b='\0';
  877.             strncatbuff(b,url_md5(fil_complete),(tok == 'Q')?32:4);
  878.             b+=strlen(b);   // pointer α la fin
  879.             break;
  880.           case 'r': case 'R':        // protocol
  881.             *b='\0';
  882.             strcatbuff(b, protocol_str[protocol]);
  883.             b+=strlen(b);   // pointer α la fin
  884.           break;
  885.         }
  886.       } else
  887.         *b++=*a++;
  888.     }
  889.     *b++='\0';
  890.     //
  891.     // Types prΘdΘfinis
  892.     //
  893.  
  894.   } 
  895.   //
  896.   // Structure originale
  897.   else if (opt->savename_type%100==0) { 
  898.     /* recopier www.. */
  899.     if (opt->savename_type!=100) {  
  900.       if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  901.         if (strcmp(adr_complete,"file://")==0) {
  902.           //## if (*adr==lOCAL_CHAR) {
  903.           if (opt->savename_83 != 1)  // noms longs
  904.             strcatbuff(save,"localhost");
  905.           else
  906.             strcatbuff(save,"local");
  907.         } else {
  908.           // adresse url
  909.           if (!opt->savename_83) {  // noms longs (et pas de .)
  910.             strcatbuff(save,print_adr);
  911.           } else {  // noms 8-3
  912.             if (strlen(print_adr)>4) {
  913.               if (strfield(print_adr,"www."))
  914.                 strncatbuff(save,print_adr+4,max_char);
  915.               else
  916.                 strncatbuff(save,print_adr,8);
  917.             } else strncatbuff(save,print_adr,max_char);
  918.           }
  919.         }
  920.         if (*fil!='/') strcatbuff(save,"/");
  921.       }
  922.     }
  923.   
  924. #if HTS_CASSE==0
  925.     hts_lowcase(save);
  926. #endif  
  927.         
  928.     /*
  929.     // ne sert α rien car a dΘja ΘtΘ filtrΘ normalement
  930.     if ((*fil=='.') && (*(fil+1)=='/'))          // ./index.html ** //
  931.       url_savename_addstr(save,fil+2);
  932.     else                                               // index.html ou /index.html
  933.       url_savename_addstr(save,fil);
  934.     if (save[strlen(save)-1]=='/') 
  935.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  936. */
  937.  
  938.     /* add name */
  939.     ADD_STANDARD_PATH;
  940.     ADD_STANDARD_NAME(0);
  941.  
  942.   }
  943.   //
  944.   // Structure html/image
  945.   else {    
  946.     // dossier "web" ou "www.xxx" ?
  947.     if (((opt->savename_type/1000)%2)==0) {    // >1000 signifie "pas de www/"
  948.       if ((opt->savename_type/100)%2) {
  949.         if (strcmp(adr_complete,"file://")==0) {
  950.         //## if (*adr==lOCAL_CHAR) {
  951.           if (opt->savename_83 != 1)  // noms longs
  952.             strcatbuff(save,"localhost/");
  953.           else
  954.             strcatbuff(save,"local/");
  955.         } else {
  956.           // adresse url
  957.           if (!opt->savename_83) {  // noms longs
  958.             strcatbuff(save,print_adr); strcatbuff(save,"/");
  959.           } else {  // noms 8-3
  960.             if (strlen(print_adr)>4) {
  961.               if (strfield(print_adr,"www."))
  962.                 strncatbuff(save,print_adr+4,max_char);
  963.               else
  964.                 strncatbuff(save,print_adr,max_char);
  965.               strcatbuff(save,"/");
  966.             } else { 
  967.               strncatbuff(save,print_adr,max_char); strcatbuff(save,"/");
  968.             }
  969.           }
  970.         }
  971.       } else {
  972.         strcatbuff(save,"web/");    // rΘpertoire gΘnΘral
  973.       }
  974.     } 
  975.  
  976.     // si un html α coup s√r
  977.     if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  978.       if (opt->savename_type%100==2) {  // html/
  979.         strcatbuff(save,"html/");
  980.       }
  981.     } else {
  982.       if ((opt->savename_type%100==1) || (opt->savename_type%100==2)) {  // html & images
  983.         strcatbuff(save,"images/");
  984.       }
  985.     }
  986.     
  987.     switch (opt->savename_type%100) {
  988.     case 4: case 5: {           // sΘparer par types
  989.       char* a=fil+strlen(fil)-1;
  990.       // passer structures
  991.       while(( a > fil) && (*a != '/') && (*a != '\\')) a--;      
  992.       if ((*a=='/') || (*a=='\\')) a++;
  993.  
  994.       // html?
  995.       if ( (ext_chg!=0) ? (ishtml_ext(ext)==1) : (ishtml(fil)==1) ) {
  996.         if (opt->savename_type%100==5)
  997.           strcatbuff(save,"html/");
  998.       } else {
  999.         char* a=fil+strlen(fil)-1;
  1000.         while(( a> fil) && (*a != '/') && (*a != '.')) a--;      
  1001.         if (*a!='.')
  1002.           strcatbuff(save,"other");
  1003.         else
  1004.           strcatbuff(save,a+1);
  1005.         strcatbuff(save,"/");
  1006.       }
  1007.       /*strcatbuff(save,a);*/
  1008.       /* add name */
  1009.       ADD_STANDARD_NAME(0);
  1010.             }
  1011.       break;
  1012.     case 99: {                  // 'codΘ' .. c'est un gadget
  1013.       int i;
  1014.       int j;
  1015.       char* a;
  1016.       char C[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
  1017.       int L;
  1018.       // pseudo-CRC sur fil et adr pour initialiser gΘnΘrateur alΘatoire..
  1019.       unsigned int s=0;
  1020.       L=strlen(C);
  1021.       for(i=0;i<(int) strlen(fil_complete);i++) {
  1022.         s+=(unsigned int) fil_complete[i];
  1023.       }
  1024.       for(i=0;i<(int) strlen(adr_complete);i++) {
  1025.         s+=(unsigned int) adr_complete[i];
  1026.       }
  1027.       srand(s);
  1028.       
  1029.       j=strlen(save);
  1030.       for(i=0;i<8;i++) {
  1031.         char c=C[(rand()%L)];
  1032.         save[i+j]=c;
  1033.       }
  1034.       save[i+j]='\0';
  1035.       // ajouter extension
  1036.       a=fil+strlen(fil)-1;
  1037.       while(( a > fil) && (*a != '/') && (*a != '.')) a--;
  1038.       if (*a=='.') {
  1039.         strcatbuff(save,a);    // ajouter
  1040.       }
  1041.              } 
  1042.       break;
  1043.     default: {   // noms sans les noms des rΘpertoires
  1044.       // ne garder que le nom, pas la structure
  1045.       /*
  1046.       char* a=fil+strlen(fil)-1;
  1047.       while(((int) a>(int) fil) && (*a != '/') && (*a != '\\')) a--;      
  1048.       if ((*a=='/') || (*a=='\\')) a++;
  1049.       strcatbuff(save,a);
  1050.       */
  1051.  
  1052.       /* add name */
  1053.       ADD_STANDARD_NAME(0);
  1054.             }
  1055.       break;
  1056.     }
  1057.  
  1058. #if HTS_CASSE==0
  1059.     hts_lowcase(save);
  1060. #endif  
  1061.  
  1062.     if (save[strlen(save)-1]=='/') 
  1063.       strcatbuff(save,DEFAULT_HTML);     // nommer page par dΘfaut!!
  1064.   }
  1065.  
  1066.  
  1067.   // vΘrifier qu'on ne doit pas forcer l'extension
  1068.   // par exemple, asp sera sauvΘ en html, cgi en html ou gif, xbm etc.. selon les cas
  1069.   /*if (ext_chg) {
  1070.     char* a=save+strlen(save)-1;
  1071.     while(((int) a>(int) save) && (*a!='.') && (*a!='/')) a--;
  1072.     if (*a=='.') *a='\0';  // couper
  1073.     // recopier extension
  1074.     strcatbuff(save,".");
  1075.     strcatbuff(save,ext);    // copier ext
  1076.   }*/
  1077.   // de mΩme en cas de manque d'extension on en place une de maniΦre forcΘe..
  1078.   // cela Θvite les /chez/toto et les /chez/toto/index.html incompatibles
  1079.   if (opt->savename_type != -1) {
  1080.     char* a=save+strlen(save)-1;
  1081.     while(( a > save) && (*a!='.') && (*a!='/')) a--;
  1082.     if (*a!='.') {   // agh pas de point
  1083.       //strcatbuff(save,".none");                 // a Θviter
  1084.       strcatbuff(save,".html");                   // prΘfΘrable!
  1085.       if ( (opt->debug>1) && (opt->errlog!=NULL) ) {
  1086.         fspc(opt->errlog,"warning"); fprintf(opt->errlog,"Default HTML type set for %s%s"LF,adr_complete,fil_complete);
  1087.         test_flush;
  1088.       }
  1089.     }
  1090.   }
  1091.  
  1092.   // effacer pass au besoin pour les autentifications
  1093.   // (plus la peine : masquΘ au dΘbut)
  1094. /*
  1095.   {
  1096.     char* a=jump_identification(save);
  1097.     if (a!=save) {
  1098.       char tempo[HTS_URLMAXSIZE*2];
  1099.       char *b;
  1100.       tempo[0]='\0';
  1101.       strcpybuff(tempo,"[");
  1102.       b=strchr(save,':');
  1103.       if (!b) b=strchr(save,'@');
  1104.       if (b)
  1105.         strncatbuff(tempo,save,(int) b-(int) a);
  1106.       strcatbuff(tempo,"]");
  1107.       strcatbuff(tempo,a);
  1108.       strcpybuff(save,a);
  1109.     }
  1110.   }
  1111. */
  1112.  
  1113.   // Θviter les / au dΘbut (cause: N100)
  1114.   if (save[0]=='/') {
  1115.     char tempo[HTS_URLMAXSIZE*2];
  1116.     strcpybuff(tempo,save+1);
  1117.     strcpybuff(save,tempo);
  1118.   }
  1119.  
  1120.   // changer les ~,:,",*,? en _ pour sauver sur disque
  1121.   hts_replace(save,'~','_');  // interdit sous unix (~foo)
  1122.   //
  1123.   hts_replace(save,'\\','_');
  1124.   hts_replace(save,':','_');  // interdit sous windows
  1125.   hts_replace(save,'*','_');  // interdit sous windows
  1126.   hts_replace(save,'?','_');  // doit pas arriver!!
  1127.   hts_replace(save,'\"','_');  // interdit sous windows
  1128.   hts_replace(save,'<','_');  // interdit sous windows
  1129.   hts_replace(save,'>','_');  // interdit sous windows
  1130.   hts_replace(save,'|','_');  // interdit sous windows
  1131.   //
  1132.   hts_replace(save,'@','_');
  1133.   if (opt->savename_83 == 2) { // CDROM
  1134.     // maybe other ones?
  1135.     hts_replace(save,'-','_');
  1136.     hts_replace(save,'=','_');
  1137.     hts_replace(save,'+','_');
  1138.   }
  1139.   //
  1140.   { // Θliminer les // (comme ftp://)
  1141.     char* a;
  1142.     while( (a=strstr(save,"//")) ) *a='_';
  1143.     // Eliminer chars spΘciaux
  1144.     a=save -1 ;
  1145.     while(*(++a))
  1146.       if ( ((unsigned char)(*a) <= 31)
  1147.           || ((unsigned char)(*a) == 127) )
  1148.         *a='_';
  1149.   }
  1150.  
  1151.    
  1152. #if HTS_OVERRIDE_DOS_FOLDERS
  1153.   /* Replace /foo/nul/bar by /foo/nul_/bar */
  1154.   {
  1155.     int i=0;
  1156.     while(hts_tbdev[i][0]) {
  1157.       char* a=save;
  1158.       while((a=strstrcase(a,(char*)hts_tbdev[i]))) {
  1159.         switch ( (int) a[strlen(hts_tbdev[i])] ) {
  1160.         case '\0':
  1161.         case '/':
  1162.         case '.': 
  1163.         {
  1164.           char tempo[HTS_URLMAXSIZE*2]; tempo[0]='\0';
  1165.           strncatbuff(tempo,save,(int) (a - save) + strlen(hts_tbdev[i]));
  1166.           strcatbuff(tempo,"_");
  1167.           strcatbuff(tempo,a+strlen(hts_tbdev[i]));
  1168.           strcpybuff(save,tempo);
  1169.                    }
  1170.           break;
  1171.         }
  1172.         a+=strlen(hts_tbdev[i]);
  1173.       }
  1174.       i++;
  1175.     }
  1176.   }
  1177.   /* Strip ending . or ' ' forbidden on windoz */
  1178.   {
  1179.     int len;
  1180.     char* a=save;
  1181.     while((a=strstr(a,"./"))) {
  1182.       *a = '_';
  1183.     }
  1184.     a=save;
  1185.     while((a=strstr(a," /"))) {
  1186.       *a = '_';
  1187.     }
  1188.     len = (int) strlen(save);
  1189.     if (len > 0 && ( save[len - 1] == '.' || save[len - 1] == ' ') ) {
  1190.       save[len - 1] = '_';
  1191.     }
  1192.   }
  1193. #endif
  1194.  
  1195.   // conversion 8-3 .. y compris pour les rΘpertoires
  1196.   if (opt->savename_83) {
  1197.     char n83[HTS_URLMAXSIZE*2];
  1198.     long_to_83(opt->savename_83,n83,save);
  1199.     strcpybuff(save,n83);
  1200.   }
  1201.  
  1202.  
  1203.   /* ensure that there is no ../ (potential vulnerability) */
  1204.   fil_simplifie(save);
  1205.  
  1206. #if HTS_ANALYSTE
  1207.   {
  1208.     hts_htmlcheck_savename(adr_complete,fil_complete,referer_adr,referer_fil,save);
  1209.     if ( (opt->debug>0) && (opt->log!=NULL) ) {
  1210.       fspc(opt->log,"info"); fprintf(opt->log,"engine: save-name: local name: %s%s -> %s"LF,adr,fil,save);
  1211.       test_flush;
  1212.     }
  1213.   }
  1214. #endif
  1215.  
  1216.   // chemin primaire Θventuel A METTRE AVANT
  1217.   if (strnotempty(opt->path_html)) {
  1218.     char tempo[HTS_URLMAXSIZE*2];
  1219.     strcpybuff(tempo,opt->path_html);
  1220.     strcatbuff(tempo,save);
  1221.     strcpybuff(save,tempo);
  1222.   }
  1223.  
  1224.  
  1225.   // vΘrifier que le nom n'est pas dΘja pris...
  1226.   if (liens!=NULL) { 
  1227.     int nom_ok;
  1228.     do {
  1229.       int i;
  1230.       int len;
  1231.       len=strlen(save);    // taille
  1232.       //
  1233.       nom_ok=1;  // α priori bon
  1234.       // on part de la fin pour optimiser, plus les opti de taille pour aller encore plus vite..
  1235. #if DEBUG_SAVENAME
  1236. printf("\nStart search\n");
  1237. #endif
  1238.  
  1239. #if HTS_HASH
  1240.       i=hash_read(hash,save,"",0,0);      // lecture type 0 (sav)
  1241.       if (i>=0)
  1242. #else
  1243.       for(i=lien_tot-1;i>=0;i--) {
  1244. #if DEBUG_SAVENAME
  1245. printf("%cParse: %d",13,i);
  1246. #endif
  1247.         
  1248.         if (liens[i]->sav_len==len) {    // mΩme taille de chaεne          
  1249. #if HTS_CASSE
  1250.           if (strcmp(liens[i]->sav,save)==0)    // existe dΘja
  1251. #else
  1252.           if (strfield2(liens[i]->sav,save))    // un tel nom existe dΘja
  1253. #endif
  1254. #endif
  1255.           {
  1256. #if HTS_CASSE
  1257.             if ((strcmp(liens[i]->adr,adr)==0) && (strcmp(liens[i]->fil,fil_complete)==0))
  1258. #else
  1259.             if ((strfield2(liens[i]->adr,adr)) && (strfield2(liens[i]->fil,fil_complete)))
  1260. #endif
  1261.             {    // ok c'est le mΩme lien, adresse dΘja dΘfinie
  1262.               //printf("Ok, %s\n",save);
  1263.               //i=lien_tot;    // sortir
  1264.               i=0;
  1265. #if DEBUG_SAVENAME
  1266. printf("\nOK ALREADY DEFINED\n",13,i);
  1267. #endif
  1268.             } else {  // utilisΘ par un AUTRE, changer de nom
  1269.               char tempo[HTS_URLMAXSIZE*2];
  1270.               char* a=save+strlen(save)-1;
  1271.               char* b;
  1272.               int n=2;       
  1273.               tempo[0]='\0';
  1274.  
  1275. #if DEBUG_SAVENAME
  1276. printf("\nWRONG CASE UNMATCH : \n%s\n%s, REDEFINE\n",liens[i]->fil,fil_complete);
  1277. #endif
  1278.               nom_ok=0;
  1279.               i=0;
  1280.               
  1281.               while(( a > save) && (*a!='.') && (*a!='\\') && (*a!='/')) a--;
  1282.               if (*a=='.')
  1283.                 strncatbuff(tempo,save,(int) (a - save));
  1284.               else
  1285.                 strcatbuff(tempo,save);
  1286.               
  1287.               // tester la prΘsence d'un -xx (ex: index-2.html -> index-3.html)
  1288.               b=tempo+strlen(tempo)-1;
  1289.               while (isdigit((unsigned char)*b)) b--;
  1290.               if (*b=='-') {
  1291.                 sscanf(b+1,"%d",&n);
  1292.                 *b='\0';    // couper
  1293.                 n++;  // plus un
  1294.               }
  1295.               
  1296.               // en plus il faut gΘrer le 8-3 .. pas facile le client
  1297.               if (opt->savename_83) {
  1298.                 int max;
  1299.                 char* a=tempo+strlen(tempo)-1;
  1300.                 while(( a > tempo) && (*a!='/')) a--;
  1301.                 if (*a=='/') a++;
  1302.                 max=max_char-1-nombre_digit(n);
  1303.                 if ((int) strlen(a)>max)
  1304.                   *(a+max)='\0';  // couper sinon il n'y aura pas la place!
  1305.               }
  1306.               
  1307.               // ajouter -xx (ex: index.html -> index-2.html)
  1308.               sprintf(tempo+strlen(tempo),"-%d",n);
  1309.               
  1310.               // ajouter extension
  1311.               if (*a=='.')
  1312.                 strcatbuff(tempo,a);
  1313.               
  1314.               strcpybuff(save,tempo);
  1315.               
  1316.               //printf("switched: %s\n",save);
  1317.               
  1318.             }  // if
  1319. #if HTS_HASH
  1320.           }
  1321. #else
  1322.           }  // if
  1323.         }  // if sav_len
  1324.       }  // for
  1325. #endif
  1326. #if DEBUG_SAVENAME
  1327. printf("\nEnd search, %s\n",fil_complete);
  1328. #endif
  1329.     } while(!nom_ok);
  1330.     
  1331.   }
  1332.   
  1333.   //printf("'%s' %s %s\n",save,adr,fil);
  1334.       
  1335.   return 0;
  1336. }
  1337.  
  1338. /* nom avec md5 urilisΘ partout */
  1339. void standard_name(char* b,char* dot_pos,char* nom_pos,char* fil_complete,int short_ver) {
  1340.   b[0]='\0';
  1341.   /* Nom */
  1342.   if (dot_pos) {
  1343.     if (!short_ver)    // Noms longs
  1344.       strncatbuff(b,nom_pos,(int) (dot_pos - nom_pos));
  1345.     else
  1346.       strncatbuff(b,nom_pos,min((int) (dot_pos - nom_pos),8));
  1347.   } else {
  1348.     if (!short_ver)    // Noms longs
  1349.       strcatbuff(b,nom_pos);
  1350.     else
  1351.       strncatbuff(b,nom_pos,8);
  1352.   }
  1353.   /* MD5 - 16 bits */
  1354.   strncatbuff(b,url_md5(fil_complete),4);
  1355.   /* Ext */
  1356.   if (dot_pos) {
  1357.     strcatbuff(b,".");
  1358.     if (!short_ver)    // Noms longs
  1359.       strcatbuff(b,dot_pos+1);
  1360.     else
  1361.       strncatbuff(b,dot_pos+1,3);
  1362.   } else {
  1363.     if (!short_ver)    // Noms longs
  1364.       strcatbuff(b,DEFAULT_EXT);    // pas de..
  1365.     else
  1366.       strcatbuff(b,DEFAULT_EXT_SHORT);    // pas de..
  1367.   }
  1368. }
  1369.  
  1370.  
  1371. /* Petit md5 */
  1372. char* url_md5(char* fil_complete) {
  1373.   char* digest;
  1374.   char* a;
  1375.   NOSTATIC_RESERVE(digest, char, 32+2);
  1376.   digest[0]='\0';
  1377.   a=strchr(fil_complete,'?');
  1378.   if (a) {
  1379.     if (strlen(a)) {
  1380.       char buff[HTS_URLMAXSIZE*2];
  1381.       a++;
  1382.       digest[0]=buff[0]='\0';
  1383.       strcatbuff(buff,a);         /* query string MD5 */
  1384.       domd5mem(buff,strlen(buff),digest,1);
  1385.     }
  1386.   }
  1387.   return digest;
  1388. }
  1389.  
  1390. // interne α url_savename: ajoute une chaεne α une autre avec \ -> /
  1391. void url_savename_addstr(char* d,char* s) {
  1392.   int i=strlen(d);
  1393.   while(*s) {
  1394.     if (*s=='\\')  // remplacer \ par des /
  1395.       d[i++]='/';
  1396.     else
  1397.       d[i++]=*s;
  1398.     s++;
  1399.   }
  1400.   d[i]='\0';
  1401. }
  1402.  
  1403. #undef test_flush
  1404.